package xyz.qduwo.service;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;


import net.sf.json.JSONObject;
import xyz.qduwo.dao.RoomDao;
import xyz.qduwo.entity.RoomEntity;
import xyz.qduwo.entity.UserEntity;
import xyz.qduwo.util.CommonUtils;
import xyz.qduwo.util.GetHttpSessionConfigurator;


@ServerEndpoint(value="/websocket/{info}",configurator=GetHttpSessionConfigurator.class)
public class WebSocketService {
    private static SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");//创建时间格式对象
    //concurrent包的线程安全Set，用来存放每个客户端对应的WebSocketService对象。
    //创建一个房间的集合，用来存放房间
    private static ConcurrentHashMap<String,ConcurrentHashMap<String, WebSocketService>> roomList = new  ConcurrentHashMap<String,ConcurrentHashMap<String, WebSocketService>>();
    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    //重新加入房间的标示；
    private int rejoin = 0;
    //画布操作日志，复原现场时使用
    private static CopyOnWriteArraySet<JSONObject> log = new CopyOnWriteArraySet<JSONObject>();
    /**
     * 用户接入
     * @param param
     * @param session
     * @param config
     */
    @OnOpen
    public void onOpen(@PathParam(value = "info") String param,Session session,EndpointConfig config) throws IOException {
        this.session = session;
        HttpSession httpSession= (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        String flag = param.split("[|]")[0]; 		//标识
        String member = param.split("[|]")[1];		//房间号码
        UserEntity usersEntity =(UserEntity)httpSession.getAttribute("userentity");
        if(!roomList.containsKey(member)){
            System.out.println("创建房间 "+member);
            createRoom(member, usersEntity);
            roomList.put(member, new ConcurrentHashMap<>());
        }
        if(flag.equals("join")){
            String user = param.split("[|]")[2];
            joinRoom(member,user);

        }
    }
    //创建房间
    public void createRoom(String num,UserEntity user){
        Date now = new Date();
        RoomEntity roomEntity = new RoomEntity();
        roomEntity.setNum(num);
        roomEntity.setStartTime(CommonUtils.transToSqlDate(now));
        roomEntity.setInitiator(user.getId());
        RoomDao.save(roomEntity);
    }
    //加入房间
    public void joinRoom(String member,String user) throws IOException {
        ConcurrentHashMap<String, WebSocketService> r =  roomList.get(member);
        if(r.get(user) != null){		//该用户有没有出
            this.rejoin = 1;
        }
        r.put(user, this);//将此用户加入房间中
        JSONObject obj = new JSONObject();
        obj.put("date", df.format(new Date()));
        List<String> uname = new ArrayList<>();
        for(String u:r.keySet()){
            uname.add(u);
        }
        obj.put("uname", uname.toArray());
        obj.put("flag","enterroom");
        obj.put("message", user +" 进入了房间");
        obj.put("content",log);
        obj.put("isSelf",true);//设置消息是否为自己的
        this.sendMessage(obj.toString());
        obj.put("isSelf",false);//设置消息是否为自己的
        obj.remove("content");
        for(String i:r.keySet()){  //遍历该房间
            if(!user.equals(i)){
                r.get(i).sendMessage(obj.toString());//调用方法 将消息推送
            }

        }

    }
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }
    /**
     * 接收到来自用户的消息
     * @param message
     * @param session
     * @throws IOException
     */
    @OnMessage
    public void onMessage(String message,Session session) throws IOException{
        //把用户发来的消息解析为JSON对象
        JSONObject obj = JSONObject.fromObject(message);
        if(obj.get("flag").toString().equals("exitroom")){		//退出房间操作
            String roomid = obj.get("roomid").toString();
            //将用户从聊天室中移除
            int f2 = 1;
            roomList.get(roomid).remove(obj.get("nickname").toString());//将用户直接移除
            if(roomList.get(roomid).isEmpty()){//判断房间该房间是否还有用户，如果没有，则将此房间也移除
                f2 = 2;
            }
            if(f2 == 1){		//证明该房间还有其它成员，则通知其它成员更新列表
                obj.put("flag","exitroom");
                String m = obj.get("nickname").toString()+" 退出了房间";
                obj.put("message", m);
                ConcurrentHashMap<String, WebSocketService> r =roomList.get(roomid);
                List<String> uname = new ArrayList<>();
                for(String u:r.keySet()){
                    uname.add(u);
                }
                obj.put("uname", uname.toArray());
                for(String i:r.keySet()){  //遍历该房间
                    r.get(i).sendMessage(obj.toString());//调用方法 将消息推送
                }
            }if(f2==2){
                //房间空，删除房间
                System.out.println("删除房间 "+roomid);
                roomList.remove(roomid);
                RoomEntity room = RoomDao.getroom(roomid);
                System.out.println(room.getId());
                room.setEndTime(CommonUtils.transToSqlDate(new Date()));
                RoomDao.update(room);
            }
        }else if(obj.get("flag").toString().equals("draw")){		//画板操作的消息 加入房间/发送消息
            //向JSON对象中添加发送时间
            obj.put("date", df.format(new Date()));
            //获取客户端发送的数据中的内容---房间号 用于区别该消息是来自于哪个房间
            String roomid = obj.get("target").toString();
            //获取客户端发送的数据中的内容---用户
            String username = obj.get("nickname").toString();
            //从房间列表中定位到该房间
            ConcurrentHashMap<String, WebSocketService> r =roomList.get(roomid);
            List<String> uname = new ArrayList<>();
            for(String u:r.keySet()){
                uname.add(u);
            }
            obj.put("uname", uname.toArray());
            if(r.get(username).rejoin == 0){			//证明不是退出重连
                for(String i:r.keySet()){  //遍历该房间
                    obj.put("isSelf", username.equals(i));//设置消息是否为自己的
                    r.get(i).sendMessage(obj.toString());//调用方法 将消息推送
                }
            }else{
                obj.put("isSelf", true);
                r.get(username).sendMessage(obj.toString());
            }
            log.add((JSONObject) obj.get("content"));  //回写操作日志
            r.get(username).rejoin = 0;
        }

    }

    /**
     * 用户断开
     * @param session
     */
    @OnClose
    public void onClose(Session session){
        
        System.out.println("客户端关闭了连接");
    }

    /**
     * 用户连接异常
     * @param t
     */
    @OnError
    public void onError(Throwable t){
        System.out.println("发生错误");
    }
}
